package com.gopay.bis.cuccpay.ebank.operation;

import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.cuccpay.ebank.CuccPayMessage;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.HttpsTransport;
import com.gopay.remote.bank.ICertHelper;

/**
 * 联通沃查询实现
 * 
 * @CuccPayQuery.java
 * @author WangHongFei
 */
public class CuccPayQuery {
	private ICertHelper cuccPayCertHelper = null;
	private HttpsTransport httpsTransport = null;
	
	public Object submit(Map<String,String> param,String bankUrl) throws GopayException{
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setBank(BankConstants.BANK_LOGO_CUCCPAY);
		try {
			httpsTransport.setUrl(bankUrl); // 设置URL
			BankLogUtils.printB2CQuerySendLog(baseMessage, param);
			Object resObj = httpsTransport.submit(param); // 发送请求
			BankLogUtils.printB2CQueryBlackLog(baseMessage, (String) resObj);
			return resObj;
		} catch (Exception e) {
			BankLogUtils.printB2CQueryExceptionLog(baseMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6037);
		}
	}
	
	/**
	 * 构建请求订单查询信息
	 * 
	 * @param message
	 * @return Map
	 * @throws GopayException 
	 */
	public Map<String, String> buildQueryMsg(CuccPayMessage message) throws GopayException{
		try {
			Map<String, String> param = new HashMap<String, String>();
			param.put("merNo", message.getMerNo());
			param.put("orderNo", message.getOrderNo());
			param.put("orderDate", message.getOrderDate());
			param.put("charSet", message.getCharSet());
			param.put("signType", message.getSignType());
			param.put("signMsg", message.getSignMsg());
			return param;
		} catch (Exception e) {
			BankLogUtils.printB2CQueryExceptionLog(message, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6035);
		}
	}
	
	/**
	 * 解析订单查询返回对象
	 * 
	 * @param Object
	 * @return CuccPayMessage
	 */
	public CuccPayMessage parseQueryMsg(Object obj,String privateKey) throws GopayException{
		CuccPayMessage resMessage = new CuccPayMessage();
		resMessage.setBank(BankConstants.BANK_LOGO_CUCCPAY);
		try{
			// 解析订单查询返回对象
			resMessage = buildMsg(obj);
			// 将带签名字符串转换为Map格式
			Map<String, String> resParams = new HashMap<String, String>();
			resParams = splicingData(buildPlain(resMessage),resParams);
			// 调用签名工具类组装签名明文
			String plainMsg = getMd5SignMsg(resParams,privateKey);
			resMessage.setPlainMessage(plainMsg);
			// 验签
			boolean resFlag = (Boolean) cuccPayCertHelper.verify(resMessage);
			if (resFlag) {
				return resMessage;
			} else {
				return null;
			}
		}catch(Exception e){
			BankLogUtils.printB2CQueryExceptionLog(resMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6039);
		}
	}

	/**
	 * build message
	 * 
	 * @param Object
	 * @return CuccPayMessage
	 */
	public CuccPayMessage buildMsg(Object obj) throws Exception{
		CuccPayMessage message = new CuccPayMessage();
		// 解析返回信息
		String reciverDate = "";
		if (obj instanceof byte[]) {
			reciverDate = new String((byte[]) obj);
		} else if (obj instanceof String) {
			reciverDate = (String) obj;
		}
		//返回的数据stream格式为： Key1=value1 加换行符：[\n] Key2=value2 加换行符：[\n]
		String[] ls = reciverDate.split("\\\n");
		for (int i = 0; i < ls.length; i++) {
			String currentResult = (String) ls[i];
			if (currentResult == null || currentResult.equals("")) {
				continue;
			}
			int j = currentResult.indexOf("=");
			if (j >= 0) {
				String sKey = currentResult.substring(0, j);
				String sValue = currentResult.substring(j + 1);
				sValue = URLDecoder.decode(sValue, "GBK");
				if (sKey.equals("queryResult")) {
					message.setQueryResult(sValue);
				} else if (sKey.equals("orderState")) {
					message.setOrderState(sValue);
				} else if (sKey.equals("payJournl")) {
					message.setPayJournl(sValue);
				} else if (sKey.equals("payAmount")) {
					message.setPayAmount(sValue);
				} else if (sKey.equals("tradeType")) {
					message.setTradType(sValue);
				} else if (sKey.equals("payType")) {
					message.setPayType(sValue);
				} else if (sKey.equals("payProAmt")) {
					message.setPayProAmt(sValue);
				} else if (sKey.equals("payDate")) {
					message.setPayDate(sValue);
				} else if (sKey.equals("payBank")) {
					message.setPayBank(sValue);
				} else if (sKey.equals("refundCount")) {
					message.setRefundCount(sValue);
				} else if (sKey.equals("refundAmount")) {
					message.setRefundAmount(sValue);
				} else if (sKey.equals("orderCreateDatetime")) {
					message.setOrderCreateDatetime(sValue);
				} else if (sKey.equals("detail")) {
					message.setDetail(sValue);
				} else if (sKey.equals("signType")) {
					message.setSignType(sValue);
				} else if (sKey.equals("signMsg")) {
					message.setSignMsg(sValue);
				}
			}
		}
		return message;
	}

	
	public String buildPlain(CuccPayMessage cuMessage) throws Exception{
		StringBuffer sb = new StringBuffer("");
		// 从a 到z 的顺序排序
		sb.append("detail=").append(cuMessage.getDetail());
		sb.append("|orderCreateDatetime=").append(cuMessage.getOrderCreateDatetime());
		sb.append("|orderState=").append(cuMessage.getOrderState());
		sb.append("|payAmount=").append(cuMessage.getPayAmount());
		sb.append("|payBank=").append(cuMessage.getPayBank());
		sb.append("|payDate=").append(cuMessage.getPayDate());
		sb.append("|payJournl=").append(cuMessage.getPayJournl());
		sb.append("|payProAmt=").append(cuMessage.getPayProAmt());
		sb.append("|payType=").append(cuMessage.getPayType());
		sb.append("|queryResult=").append(cuMessage.getQueryResult());
		sb.append("|refundAmount=").append(cuMessage.getRefundAmount());
		sb.append("|refundCount=").append(cuMessage.getRefundCount());
		sb.append("|signType=").append(cuMessage.getSignType());
		sb.append("|tradeType=").append(cuMessage.getTradType());
		return sb.toString();
	}

	/**
	 * 将签名字符串转换成Map
	 * 
	 * @param str 签名字符串
	 * @param params 签名Map
	 * @param split 分隔符“=”
	 * @return Map
	 */
	private Map<String, String> splicingData(String str,Map<String, String> params) throws Exception{
		String split = "\\=";
		String[] data = str.split("\\|");
		for (int i = 0; i < data.length; i++) {
			String methods = data[i];
			String[] method = methods.split(split);
			String key = method[0];
			String value = null;
			if (method.length >= 2) {
				value = "".equals(method[1]) || "null".equals(method[1]) ? null
						: method[1];
			} else {
				value = null;
			}
			params.put(key, value);
		}
		return params;
	}
	
	/**
	 * 生成MD5方式签名的签名结果
	 * 
	 * @param sArray 要签名的数组
	 * @param key 签名密码
	 * @return 签名结果字符串
	 */
	private String getMd5SignMsg(Map<String, String> params, String key) throws Exception{
		params = doFilterParam(params);
		String signSource = createLinkString(params);
		if (key != null && key.length() > 0) {// 证书签名时签名密码为空
			signSource = signSource + "|key=" + key;
		}
		return signSource;
	}
	
	/**
	 * 处理数组中的null值和除去非签名参数
	 * 
	 * @param params 签名参数组
	 * @return 去掉空值与签名参数后的新签名参数组
	 */
	private Map<String, String> doFilterParam(Map<String, String> params) throws Exception{
		List<String> keys = new ArrayList<String>(params.keySet());
		Map<String, String> newParam = new HashMap<String, String>();

		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = params.get(key);

			if ("hmac".equalsIgnoreCase(key) || "signMsg".equalsIgnoreCase(key)
					|| "cert".equalsIgnoreCase(key)) {
				continue;
			}
			if (value == null || value.length() == 0) {
				continue;
			}
			newParam.put(key, value);
		}

		return newParam;
	}

	/**
	 * 把数组所有元素排序，并按照“参数=参数值”的模式用“|”字符拼接成字符串
	 * 
	 * @param params 需要排序并参与字符拼接的参数组
	 * @return 拼接后字符串
	 */
	private String createLinkString(Map<String, String> params) throws Exception{
		List<String> keys = new ArrayList<String>(params.keySet());
		Collections.sort(keys);

		StringBuffer prestr = new StringBuffer("");

		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = params.get(key);

			if (i == keys.size() - 1) {// 拼接时，不包括最后一个|字符
				prestr.append(key).append("=").append(value);
			} else {
				prestr.append(key).append("=").append(value).append("|");
			}
		}
		return prestr.toString();
	}
	
	public void setCuccPayCertHelper(ICertHelper cuccPayCertHelper) {
		this.cuccPayCertHelper = cuccPayCertHelper;
	}
	
	public void setHttpsTransport(HttpsTransport httpsTransport) {
		this.httpsTransport = httpsTransport;
	}
}
